home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / accconvolve.c next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  3.9 KB  |  224 lines

  1. #include <assert.h>
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <GL/glut.h>
  6. #include "texture.h"
  7.  
  8. static char defaultFile[] = "data/mandrill256.rgb";
  9. GLuint *img;
  10. GLsizei w, h;
  11. GLint comp;
  12.  
  13. GLfloat kernScale;
  14.  
  15. /* a few filters... */
  16. GLfloat horizontalEdge3x3[] = {
  17.     -1, -1, -1,
  18.     2,  2,  2,
  19.     -1, -1, -1,
  20. };
  21.  
  22. GLfloat verticalEdge3x3[] = {
  23.     -1,  2, -1,
  24.     -1,  2, -1,
  25.     -1,  2, -1,  
  26. };
  27.  
  28. GLfloat allEdge3x3[] = {
  29.     -2, 1, -2,
  30.     1, 4,  1,
  31.     -2, 1, -2,
  32. };
  33.  
  34. GLfloat smooth3x3[] = {
  35.     1, 2, 1,
  36.     2, 4, 2,
  37.     1, 2, 1,
  38. };
  39.  
  40. GLfloat highpass3x3[] = {
  41.     -1, -1, -1, 
  42.     -1,  9, -1,
  43.     -1, -1, -1,
  44. };
  45.  
  46. GLfloat laplacian5x5[] = {
  47.     1,  1,  1,  1,  1,  
  48.     1,  1,  1,  1,  1,  
  49.     1,  1, 24,  1,  1,  
  50.     1,  1,  1,  1,  1,  
  51.     1,  1,  1,  1,  1,  
  52. };
  53.  
  54. GLfloat box3x3[] = {
  55.     1, 1, 1,
  56.     1, 1, 1,
  57.     1, 1, 1,
  58. };
  59.  
  60. GLfloat box5x5[] = {
  61.     1, 1, 1, 1, 1, 
  62.     1, 1, 1, 1, 1, 
  63.     1, 1, 1, 1, 1, 
  64.     1, 1, 1, 1, 1, 
  65.     1, 1, 1, 1, 1, 
  66. };
  67.  
  68. struct Kernel {
  69.     const char *name;
  70.     GLfloat *kern;
  71.     GLsizei w, h;
  72. } filters[] = {
  73.     {"horizontal edge detect", horizontalEdge3x3, 3, 3},
  74.     {"vertical edge detect", verticalEdge3x3, 3, 3},
  75.     {"all edge detect", allEdge3x3, 3, 3},
  76.     {"3x3 smooth", smooth3x3, 3, 3},
  77.     {"3x3 highpass", highpass3x3, 3, 3},
  78.     {"5x5 laplacian", laplacian5x5, 5, 5},
  79.     {"3x3 box", box3x3, 3, 3},
  80.     {"5x5 box", box5x5, 5, 5},
  81. };
  82. struct Kernel *kern;
  83.  
  84. void kern_normalize(void)
  85. {
  86.     GLfloat total, scale, *k;
  87.     int i;
  88.  
  89.     k = kern->kern;
  90.     total = 0;
  91.     for (i = 0; i < kern->w*kern->h; i++) {
  92.     total += *k++;
  93.     }
  94.  
  95.     if (!total) {
  96.     /* kernel sums to 0... */
  97.     return;
  98.     } else {
  99.     scale = 1. / total;
  100.     k = kern->kern;
  101.     for (i = 0; i < kern->w * kern->h; i++) {
  102.         *k *= scale;
  103.         k++;
  104.     }
  105.     }
  106. }
  107.  
  108. GLfloat acc_kern_scale(void)
  109. {
  110.     GLfloat minPossible = 0, maxPossible = 1;
  111.     GLfloat *k;
  112.     int i;
  113.   
  114.     k = kern->kern;
  115.     for (i = 0; i < kern->w*kern->h; i++) {
  116.     if (*k < 0) {
  117.         minPossible += *k;
  118.     } else {
  119.         maxPossible += *k;
  120.     }
  121.     k++;
  122.     }
  123.  
  124.     return(1. / ((-minPossible > maxPossible) ? -minPossible : maxPossible));
  125. }
  126.  
  127. void init(void)
  128. {
  129.     kern = &filters[4];
  130.     kern_normalize();
  131.     kernScale = acc_kern_scale();
  132. }
  133.  
  134. void load_img(const char *fname)
  135. {
  136.     img = read_texture(fname, &w, &h, &comp);
  137.     if (!img) {
  138.     fprintf(stderr, "Could not open %s\n", fname);
  139.     exit(1);
  140.     }
  141. }
  142.  
  143. void reshape(GLsizei winW, GLsizei winH) 
  144. {
  145.     glViewport(0, 0, w, h);
  146.     glLoadIdentity();
  147.     glOrtho(0, winW, 0, winH, 0, 5);
  148. }
  149.  
  150. void acc_convolve(void)
  151. {
  152.     int x, y;
  153.  
  154.     for (y = 0; y < kern->h; y++) {
  155.     for (x = 0; x < kern->w; x++) {
  156.         glRasterPos2i(0, 0); 
  157.         glBitmap(0, 0, 0, 0, -x, -y, 0);
  158.         glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, img);
  159.         glAccum(GL_ACCUM, kern->kern[y*kern->w + x]*kernScale);
  160.     }
  161.     }
  162.     glAccum(GL_RETURN, 1./kernScale);
  163. }
  164.  
  165. void draw(void)
  166. {
  167.     GLenum err;
  168.  
  169.     glutSetCursor(GLUT_CURSOR_WAIT);
  170.  
  171.     glClear(GL_COLOR_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);
  172.  
  173.     acc_convolve();
  174.  
  175.     err = glGetError();
  176.     if (err != GL_NO_ERROR) printf("Error:  %s\n", gluErrorString(err));
  177.  
  178.     glutSetCursor(GLUT_CURSOR_INHERIT);
  179. }
  180.  
  181. /* ARGSUSED1 */
  182. void key(unsigned char key, int x, int y)
  183. {
  184.     if (key == 27) exit(0);
  185. }
  186.  
  187. void menu(int val)
  188. {
  189.     kern = &filters[val];
  190.     kern_normalize();
  191.     kernScale= acc_kern_scale();
  192.     draw();
  193. }
  194.  
  195. main(int argc, char *argv[])
  196. {
  197.     int i;
  198.  
  199.     glutInit(&argc, argv);
  200.     if (argc > 1) {
  201.     load_img(argv[1]);
  202.     } else {
  203.     load_img(defaultFile);
  204.     }
  205.     glutInitWindowSize(w, h);
  206.     glutInitWindowPosition(0, 0);
  207.     glutInitDisplayMode(GLUT_RGB | GLUT_ACCUM);
  208.     glutCreateWindow(argv[0]);
  209.     glutDisplayFunc(draw);
  210.     glutKeyboardFunc(key);
  211.     glutReshapeFunc(reshape);
  212.   
  213.     glutCreateMenu(menu);
  214.     for (i = 0; i < sizeof(filters) / sizeof(filters[0]); i++) {
  215.     glutAddMenuEntry(filters[i].name, i);
  216.     }
  217.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  218.   
  219.     init();
  220.   
  221.     glutMainLoop();
  222.     return 0;
  223. }
  224.